Imports cmplib01
Imports System.Drawing.Drawing2D

Public Class FlexMapViewCampaignBuilder
    Inherits FlexMapViewerC

    Private m_RuleColor(10) As Color

    Shadows Event DisplayClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs)
    Shadows Event MapScroll()
    Shadows Event Rendered()
    Shadows Event UndoRequest()
    'Shadows Event EnterPressed()
    Shadows Event BackspacePressed()
    Shadows Event DisplayMouseMove(ByVal e As System.Windows.Forms.MouseEventArgs)
    Shadows Event DisplayMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
    Public Event ObjectiveSelected()
    Public Event DeploymentZoneSelected()

    Const c_Module As String = "FlexMapViewCampaignBuilder"
    Const c_SelectionDistance As Int16 = 16  ' this is used to select a chit

    Private ptrCurrentGameData As cmplib01.CampaignerGameData
    Private isChitSelected As Boolean = False
    Private isDeploymentZoneSelected As Boolean = False

    Private m_DeploymentZoneColor As Color = Color.FromArgb(120, 150, 150, 255)
    Private m_OpposingZoneColor As Color = Color.FromArgb(120, 120, 60, 60)
    Private m_ShowZOC As Boolean = True
    Private m_ShowLOS As Boolean = True
    Private m_ShowDeploymentZones As Boolean = True
    Private m_ShowRuleRange As Boolean = True
    Private m_iconWidth As Int16 = 16
    Private m_iconHeight As Int16 = 16
    Private m_ShowSelectedObjectiveRuleRanges As Boolean = False
    Private m_ShowAllObjectiveRuleRanges As Boolean = False
    Private m_SelectedDeploymentZone As cmplib01.DeploymentZone
    Private m_SelectedChit As ChitMember
    Private m_ShowMapOnly As Boolean = True ' this is used to show no units or anything else (for before login and such)

    Private m_labelColor As Color = Color.Yellow
    Private m_labelSize As Int16 = 16

#Region " Windows Form Designer generated code "

    Public Sub New()
        MyBase.New()

        'This call is required by the Windows Form Designer.
        InitializeComponent()

        'Add any initialization after the InitializeComponent() call
        m_RuleColor(0) = Color.Crimson
        m_RuleColor(1) = Color.Green
        m_RuleColor(2) = Color.Brown
        m_RuleColor(3) = Color.Blue
        m_RuleColor(4) = Color.SteelBlue
        m_RuleColor(5) = Color.DarkBlue
        m_RuleColor(6) = Color.DarkGoldenrod
        m_RuleColor(7) = Color.DarkGreen
        m_RuleColor(8) = Color.DarkKhaki
        m_RuleColor(9) = Color.DarkOrange
        m_RuleColor(10) = Color.DarkSlateBlue

    End Sub

    'UserControl overrides dispose to clean up the component list.
    Protected Overloads Overrides Sub Dispose(ByVal disposing As Boolean)
        If disposing Then
            If Not (components Is Nothing) Then
                components.Dispose()
            End If
        End If
        MyBase.Dispose(disposing)
    End Sub

    'Required by the Windows Form Designer
    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer
    'It can be modified using the Windows Form Designer.  
    'Do not modify it using the code editor.
    <System.Diagnostics.DebuggerStepThrough()> Private Sub InitializeComponent()
        components = New System.ComponentModel.Container()
    End Sub

#End Region

#Region "picDisplay Events"
    Private Sub picDisplay_MouseUp(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picDisplay.MouseUp
        Dim j As New System.Windows.Forms.MouseEventArgs(e.Button, e.Clicks, e.X - MyBase.OffSetX, e.Y - MyBase.OffSetY, e.Delta)

        RaiseEvent DisplayClick(sender, j)
    End Sub

    Private Sub picDisplay_MouseMove(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picDisplay.MouseMove
        Dim j As New System.Windows.Forms.MouseEventArgs(e.Button, e.Clicks, e.X - MyBase.OffSetX, e.Y - MyBase.OffSetY, e.Delta)
        RaiseEvent DisplayMouseMove(j)
    End Sub

    Private Sub picDisplay_MouseDown(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles picDisplay.MouseDown
        Dim j As New System.Windows.Forms.MouseEventArgs(e.Button, e.Clicks, e.X - MyBase.OffSetX, e.Y - MyBase.OffSetY, e.Delta)
        RaiseEvent DisplayMouseDown(j)
    End Sub
#End Region

#Region "Properties"

    Public Property CurrentGameData() As cmplib01.CampaignerGameData
        Get
            Return ptrCurrentGameData
        End Get
        Set(ByVal Value As cmplib01.CampaignerGameData)
            ptrCurrentGameData = Value
        End Set
    End Property

    Public Property SelectedDeploymentZone() As DeploymentZone
        Get
            Return m_SelectedDeploymentZone
        End Get
        Set(ByVal Value As DeploymentZone)
            m_SelectedDeploymentZone = Value
            RedrawMap()
        End Set
    End Property

    Public Property SelectedChit() As ChitMember
        Get
            Return m_SelectedChit
        End Get
        Set(ByVal Value As ChitMember)
            m_SelectedChit = Value
        End Set
    End Property

    Public ReadOnly Property RuleColor(ByVal index As Byte) As Color
        Get
            If index > 10 Then index = 10
            Return m_RuleColor(index)
        End Get
    End Property

    Public Property ShowSelectedObjectiveRuleRanges() As Boolean
        Get
            Return m_ShowSelectedObjectiveRuleRanges
        End Get
        Set(ByVal Value As Boolean)
            m_ShowSelectedObjectiveRuleRanges = Value
            RedrawMap()
        End Set
    End Property

    Public Property ShowAllObjectiveRuleRanges() As Boolean
        Get
            Return m_ShowAllObjectiveRuleRanges
        End Get
        Set(ByVal Value As Boolean)
            m_ShowAllObjectiveRuleRanges = Value
            RedrawMap()
        End Set
    End Property

    Public Property ShowLOS() As Boolean
        Get
            Return m_ShowLOS
        End Get
        Set(ByVal Value As Boolean)
            m_ShowLOS = Value
        End Set
    End Property

    Public Property ShowZOC() As Boolean
        Get
            Return m_ShowZOC
        End Get
        Set(ByVal Value As Boolean)
            m_ShowZOC = Value
        End Set
    End Property

    Public Property ShowMapOnly() As Boolean
        Get
            Return m_ShowMapOnly
        End Get
        Set(ByVal Value As Boolean)
            m_ShowMapOnly = Value
        End Set
    End Property

#End Region

    Public Sub DeleteSelected()
        ' deletes the selected item
        If m_SelectedChit Is Nothing Then Exit Sub
        ptrCurrentGameData.Chits.remove(m_SelectedChit)
    End Sub

    Public Function SelectChit(ByVal pnt As Point) As Boolean
        ' returns true if a chit has been selected
        Dim lastDistance As Int16 = c_SelectionDistance
        Dim thisDistance As Int16
        Dim bSelected As Boolean = False

        isChitSelected = False


        Dim mem As ChitMember
        For Each mem In ptrCurrentGameData.Chits
            thisDistance = XYDistance(mem.Location, pnt)
            If thisDistance < lastDistance Then
                m_SelectedChit = mem
                lastDistance = thisDistance
                isChitSelected = True
                bSelected = True
            End If
        Next

        If bSelected Then RaiseEvent ObjectiveSelected()

        Return bSelected

    End Function

    Public Function SelectDeploymentZone(ByVal pnt As Point) As Boolean
        ' returns true if a deploymentzone has been selected

    End Function

    Overrides Sub RenderToDisplay()
        If Not MyBase.FMP Is Nothing Then
            If MyBase.Rendered_b = False Then Exit Sub
            Dim im As Image = New Bitmap(MyBase.FMP.Width, MyBase.FMP.Height)
            Dim g As Graphics = Graphics.FromImage(im)

            MyBase.FMP.Render(g, g.VisibleClipBounds, MyBase.ShowPaths, , MyBase.ZoomFactor, MyBase.ZoomFactor)

            'add bridges and labels
            MyBase.DrawRoads(g)
            DrawBridges(g)
            DrawLabels(g)
            DrawCampaignerLabels(g)

            If m_ShowMapOnly = False Then

                ' grid
                If MyBase.ShowGrid Then MyBase.DrawGrid(g)

                ' scale legend
                If MyBase.ShowScale Then MyBase.DrawScale(g)

                ' boundaries
                DrawBoundaries(g)

                ' area objectives
                DrawAreaObjectives(g)

                ' and deployment zones
                DrawDeploymentZones(g)

                ' draw ZOCs, los ranges and rule ranges, 
                DrawOptions(g)

                ' draw chits
                DrawChits(g)
            End If

            picDisplay.Image = im
            MyBase.BMP = im

            g.Dispose()
            GC.Collect()

            MyBase.Rendered_b = True
            RaiseEvent Rendered()
        End If
    End Sub

    Private Sub DrawCampaignerLabels(ByRef g As Graphics)

        If ShowLabels = False Then Exit Sub

        Dim lab As cmplib01.CampaignerLabel
        Dim fnt As New Font("arial", m_labelSize)
        Dim br As New SolidBrush(m_labelColor)

        Try
            For Each lab In Me.CurrentGameData.cLabels
                Dim pth As New GraphicsPath()
                Dim pnt As New PointF(lab.location.X, lab.location.Y)

                pth.AddString(lab.text, System.Drawing.FontFamily.GenericSerif, System.Drawing.FontStyle.Regular, m_labelSize, pnt, System.Drawing.StringFormat.GenericDefault)

                Dim bounds As RectangleF = pth.GetBounds
                Dim boundsBrush As New SolidBrush(lab.BackColor)
                ' increase the size of the box by 1 pixel all the way around
                bounds.X -= 1
                bounds.Y -= 1
                bounds.Width += 3
                bounds.Height += 3

                ' do the markbox. The markbox is a square around the actual position of the label, its basically an arrow.
                Dim markBoxSolid As New RectangleF(bounds.X - 3, bounds.Y - 3, 6, 6)
                Dim markBrush As New SolidBrush(Color.Red)
                Dim markBoxBounds As New Rectangle(markBoxSolid.X, markBoxSolid.Y, markBoxSolid.Width, markBoxSolid.Height)
                g.FillRectangle(markBrush, markBoxSolid)
                g.DrawRectangle(Pens.Black, markBoxBounds)
                markBrush.Dispose()

                Dim boundsBox As New Rectangle(bounds.X, bounds.Y, bounds.Width, bounds.Height)
                g.FillRectangle(boundsBrush, bounds)
                g.DrawRectangle(Pens.Black, boundsBox)
                boundsBrush.Dispose()

                Dim textBrush As New SolidBrush(lab.ForeColor)
                'br.Color = lab.foreColor
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias
                g.FillPath(textBrush, pth)
                g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.Default
                textBrush.Dispose()

            Next

        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try
    End Sub

    Private Sub DrawBoundaries(ByRef g As Graphics)
        If ptrCurrentGameData Is Nothing Then Exit Sub

        Dim gp As Drawing2D.GraphicsPath
        Dim bound As GenericBoundary

        Try
            For Each bound In ptrCurrentGameData.Boundaries
                Dim zonePath As New System.Drawing.Drawing2D.GraphicsPath()
                Dim pnt As PointF
                Dim lastPnt As PointF
                Dim i As Int16
                Dim boundaryPen As New Pen(bound.BoundaryColor, bound.BoundaryWidth)
                boundaryPen.DashStyle = bound.BoundaryStyle
                For Each pnt In bound.BoundaryPath.Points
                    If i <> 0 Then
                        zonePath.AddLine(lastPnt, pnt)
                        lastPnt = pnt
                    Else
                        lastPnt = pnt
                    End If
                    i += 1
                Next
                i = 0
                If bound.IsSelected Then
                    Dim selectedPen As New Pen(Color.Yellow, bound.BoundaryWidth + 2)
                    selectedPen.DashStyle = Drawing.Drawing2D.DashStyle.Solid
                    g.DrawPath(selectedPen, zonePath)
                    g.DrawPath(boundaryPen, zonePath)
                Else
                    g.DrawPath(boundaryPen, zonePath)
                End If

            Next

        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try
    End Sub

    Private Sub DrawAreaObjectives(ByRef g As Graphics)
        If ptrCurrentGameData Is Nothing Then Exit Sub

        Dim gp As Drawing2D.GraphicsPath
        Dim AO As AreaObjective

        Dim OwnedAO As New HatchBrush(HatchStyle.Cross, Color.FromArgb(30, 220, 220, 220), Color.FromArgb(120, 20, 120, 20))
        Dim UncontrolledAO As New HatchBrush(HatchStyle.WideUpwardDiagonal, Color.FromArgb(30, 220, 220, 220), Color.FromArgb(120, 20, 20, 20))
        Dim EnemyAO As New HatchBrush(HatchStyle.Cross, Color.FromArgb(30, 120, 20, 20), Color.FromArgb(120, 120, 20, 20))
        Dim ContestedAO As New HatchBrush(HatchStyle.WideDownwardDiagonal, Color.FromArgb(100, 220, 20, 20), Color.FromArgb(100, 20, 220, 20))

        Try
            For Each AO In ptrCurrentGameData.AreaObjectives
                Dim zonePath As New System.Drawing.Drawing2D.GraphicsPath()
                Dim pnt As PointF
                Dim lastPnt As PointF
                Dim i As Int16

                For Each pnt In AO.BoundaryPath.Points
                    If i <> 0 Then
                        zonePath.AddLine(lastPnt, pnt)
                        lastPnt = pnt
                    Else
                        lastPnt = pnt
                    End If
                    i += 1
                Next
                i = 0
                ' determine who's pov we are in and create the brush

                'Dim AOBrush As New Drawing2D.HatchBrush(Drawing2D.HatchStyle.Cross, Color.FromArgb(30, 220, 220, 220), Color.FromArgb(120, 20, 120, 20))
                Dim AOBrush As Drawing2D.HatchBrush

                If AO.OwningFaction = -1 Then
                    AOBrush = UncontrolledAO
                ElseIf AO.OwningFaction = ptrCurrentGameData.selectedFaction.FactionID Then
                    AOBrush = OwnedAO
                Else
                    AOBrush = EnemyAO
                End If
                ' down here we catch finally if its contested
                If AO.IsContested Then
                    AOBrush = ContestedAO
                End If

                g.FillPath(AOBrush, zonePath)
                ' if this one is selected, yellow the border
                If AO.IsSelected Then
                    g.DrawPath(Pens.Yellow, zonePath)
                Else
                    g.DrawPath(Pens.Black, zonePath)
                End If

            Next
        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try

    End Sub

    Private Sub DrawOptions(ByRef g As Graphics)
        If ptrCurrentGameData Is Nothing Then Exit Sub

        'Dim gc As cmplib01.GroundChitType
        'Dim key As String

        ' Figure out two things:
        '   one: #of pixels per mile

        Dim pixelsPerOneMile As Integer = MyBase.FMPData.MapScale.PixelCount / MyBase.FMPData.MapScale.MilesPerPixelCount

        Try
            For Each mem As ChitMember In ptrCurrentGameData.Chits
                Dim pnt As Point
                Dim optionPoint As Point
                pnt = mem.Location
                pnt.X -= (m_iconWidth / 2)
                pnt.Y -= (m_iconHeight / 2)
                optionPoint = mem.Location

                If mem.OwningFaction.Equals(ptrCurrentGameData.selectedFaction) Then
                    '// zoc
                    If m_ShowZOC And mem.ZOC > 0 Then
                        DrawZOC(g, optionPoint, mem.ZOC * pixelsPerOneMile)
                    End If
                Else
                    '// zoc
                    If m_ShowZOC And mem.ZOC > 0 Then
                        DrawZOC(g, optionPoint, mem.ZOC * pixelsPerOneMile, True)
                    End If

                End If

                '// los
                If m_ShowLOS And mem.LOS > 0 Then
                    DrawBorderedCircle(g, optionPoint, mem.LOS * pixelsPerOneMile, Color.Black, Color.White)
                End If

                '// rule range
                If m_ShowAllObjectiveRuleRanges = True Then
                    DrawRuleRange(g, mem)
                End If
            Next

            '// rule ranges
            If m_ShowSelectedObjectiveRuleRanges = True Then
                If Not m_SelectedChit Is Nothing Then
                    If m_SelectedChit.UnitType = GroundChitClass_cgd.Objective Then
                        DrawRuleRange(g, m_SelectedChit)
                    End If
                End If
            End If

        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try
    End Sub

    Private Sub DrawRuleRange(ByRef g As Graphics, ByRef GChit As ChitMember)

        'Dim rul As Rule
        Dim rult As RuleType
        Dim pnt As Point
        Dim colorIndex As Byte

        Dim pixelsPerOneMile As Integer = MyBase.FMPData.MapScale.PixelCount / MyBase.FMPData.MapScale.MilesPerPixelCount

        pnt = GChit.Location

        If GChit.UnitType = GroundChitClass_cgd.Objective Then
            For Each rult In DirectCast(GChit, InstallationChit).ptrInstallation.GCRules
                ' find the rule type
                'rult = ptrCurrentGameData.RuleTypes_g.Item(rul.ptrRule.RuleName)
                ' and then draw it! :P
                DrawBorderedCircle(g, pnt, rult.BasicRange * pixelsPerOneMile, m_RuleColor(colorIndex), Color.Black)
                colorIndex += 1
                If colorIndex = 11 Then colorIndex = 0
            Next
        End If


    End Sub

    Private Sub DrawDeploymentZones(ByRef g As Graphics)
        If ptrCurrentGameData Is Nothing Then Exit Sub

        Try
            Dim deploymentBrush As New SolidBrush(m_DeploymentZoneColor)
            Dim key As String
            Dim dep As New cmplib01.DeploymentZone()

            For Each key In ptrCurrentGameData.DeploymentZones_g.HT.Keys
                dep = ptrCurrentGameData.DeploymentZones_g.Item(key)
                Dim zonePath As New System.Drawing.Drawing2D.GraphicsPath()
                Dim pnt As PointF
                Dim lastPnt As PointF
                Dim i As Int16
                For Each pnt In dep.BoundaryPath.Points
                    If i <> 0 Then
                        zonePath.AddLine(lastPnt, pnt)
                        lastPnt = pnt
                    Else
                        lastPnt = pnt
                    End If
                    i += 1
                Next
                i = 0
                If ptrCurrentGameData.selectedFaction.FactionID = dep.FactionID Then
                    deploymentBrush.Color = m_DeploymentZoneColor
                Else
                    deploymentBrush.Color = m_OpposingZoneColor
                End If
                g.FillPath(deploymentBrush, zonePath)
                zonePath.CloseAllFigures()
                If dep Is m_SelectedDeploymentZone Then
                    g.DrawPath(Pens.GreenYellow, zonePath)
                End If

            Next
            deploymentBrush.Dispose()
        Catch ex As Exception
            HandleException(c_Module, ex)
        End Try
    End Sub

    Private Sub DrawChits(ByRef g As Graphics)

        If ptrCurrentGameData Is Nothing Then Exit Sub

        Dim gc As ChitMember


        For Each gc In ptrCurrentGameData.Chits
            Dim pnt As Point

            pnt = gc.Location
            pnt.X -= (m_iconWidth / 2)
            pnt.Y -= (m_iconHeight / 2)

            If gc Is m_SelectedChit Then
                g.FillRectangle(Brushes.Yellow, pnt.X - 2, pnt.Y - 2, m_iconWidth + 4, m_iconHeight + 4)
            End If

            If gc.OwningFaction.FactionID = ptrCurrentGameData.selectedFaction.FactionID Then
                Try
                    If gc.UnitType = GroundChitClass_cgd.Battlegroup Then
                        g.DrawImage(DirectCast(gc, BattlegroupChit).icon, pnt.X, pnt.Y, m_iconWidth, m_iconHeight)
                    ElseIf gc.UnitType = GroundChitClass_cgd.Objective Then
                        g.DrawImage(DirectCast(gc, InstallationChit).ptrInstallation.Icon(0), pnt.X, pnt.Y, m_iconWidth, m_iconHeight)
                    End If

                Catch
                    g.DrawImage(MyBase.picBlankImage.Image, pnt.X, pnt.Y, m_iconWidth, m_iconHeight)
                End Try
            Else
                Try
                    '// enemy
                    If gc.UnitType = GroundChitClass_cgd.Battlegroup Then
                        g.DrawImage(DirectCast(gc, BattlegroupChit).icon, pnt.X, pnt.Y, m_iconWidth, m_iconHeight)
                    ElseIf gc.UnitType = GroundChitClass_cgd.Objective Then
                        g.DrawImage(DirectCast(gc, InstallationChit).ptrInstallation.Icon(0), pnt.X, pnt.Y, m_iconWidth, m_iconHeight)
                    End If
                    g.DrawRectangle(Pens.Red, pnt.X, pnt.Y, m_iconWidth, m_iconHeight)
                Catch
                    g.DrawImage(MyBase.picBlankImage.Image, pnt.X, pnt.Y, m_iconWidth, m_iconHeight)
                End Try
            End If
        Next

    End Sub

End Class
